package server

import (
	"context"
	"crypto/tls"
	"device-modbus/core"
	"device-modbus/internal/biz/model"
	"device-modbus/plugin"
	"device-modbus/plugins/modbus_1/fen_su"
	"device-modbus/plugins/modbus_1/fen_xiang"
	"device-modbus/plugins/modbus_1/relay_switch"
	"device-modbus/plugins/modbus_1/tu_rang"
	"device-modbus/plugins/modbus_1/wen_du"
	"device-modbus/plugins/modbus_1/yu_liang"
	"errors"
	"fmt"
	"net"
	"os"
	"os/signal"
	"syscall"
	"time"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
)

// Server gRPC 服务实例
type Server struct {
	plugin.UnimplementedPluginServiceServer                // 嵌入默认实现（避免接口未全实现报错）
	cfg                                     Config         // 服务配置
	grpcServer                              *grpc.Server   // gRPC 原生服务实例
	listener                                net.Listener   // 网络监听器
	shutdownChan                            chan os.Signal // 信号监听通道（用于优雅关闭）
	//插件实例列表
	plugins map[string]core.SensorProtocol
}

// NewServer 创建 gRPC 服务实例
func NewServer(cfg Config) *Server {
	// 初始化信号通道（监听 SIGINT、SIGTERM 信号）
	shutdownChan := make(chan os.Signal, 1)
	signal.Notify(shutdownChan, syscall.SIGINT, syscall.SIGTERM)

	server := Server{
		cfg:          cfg,
		shutdownChan: shutdownChan,
		plugins:      make(map[string]core.SensorProtocol),
	}
	server.InitPlugin(context.Background())
	return &server
}

// --------------- 实现 PluginServiceServer 接口 ---------------

// Init 初始化插件：返回插件元信息（根据实际插件类型调整）
func (s *Server) Init(ctx context.Context, req *plugin.InitRequest) (*plugin.PluginMeta, error) {
	s.cfg.Log.Println("收到 Init 请求")
	// 模拟插件元信息（实际场景可从配置/数据库加载）
	return &plugin.PluginMeta{
		ProtocolName:    "modbus-1", // 协议唯一标识（如 modbus/mqtt）
		ProtocolVersion: "1.0.0",    // 协议版本
		PluginVersion:   "2.1.0",    // 插件自身版本
		Description:     "Modbus协议 雨量，百叶窗，风速，风向，继电器,土壤",
		Author:          "",
	}, nil
}

// 初始化插件 relay_switch.NewProtocol()以及其他目录下的协议
func (s *Server) InitPlugin(ctx context.Context) {
	s.plugins["继电器"] = relay_switch.NewProtocol()
	s.plugins["雨量"] = yu_liang.NewProtocol()
	s.plugins["风速"] = fen_su.NewProtocol()
	s.plugins["百叶窗"] = wen_du.NewProtocol()
	s.plugins["风向"] = fen_xiang.NewProtocol()
	s.plugins["土壤"] = tu_rang.NewProtocol()
}

// Ping 心跳检测：返回服务健康状态
func (s *Server) Ping(ctx context.Context, req *plugin.PingRequest) (*plugin.PingResponse, error) {
	s.cfg.Log.Printf("收到 Ping 请求，客户端时间戳: %d", req.ClientTimestamp)
	// 模拟健康检查（实际可检查数据库/依赖服务连接）
	healthStatus := true
	healthInfo := "服务正常，CPU使用率: 15%，内存使用率: 20%"

	return &plugin.PingResponse{
		ServerTimestamp: time.Now().UnixMilli(), // 服务端时间戳（毫秒）
		IsHealthy:       healthStatus,
		StatusInfo:      healthInfo,
	}, nil
}

// GetType 返回支持的传感器类型
func (s *Server) GetType(ctx context.Context, req *plugin.GetTypeRequest) (*plugin.GetTypeResponse, error) {
	s.cfg.Log.Println("收到 GetType 请求")
	// 实际场景可从插件配置加载支持的类型
	return &plugin.GetTypeResponse{
		Type:           "Modbus协议",                                     // 默认类型
		SupportedTypes: []string{"雨量", "百叶窗", "风速", "风向", "继电器", "土壤"}, // 支持的所有类型
	}, nil
}

// GetModel 返回支持的传感器模型
func (s *Server) GetModel(ctx context.Context, req *plugin.GetModelRequest) (*plugin.GetModelResponse, error) {
	s.cfg.Log.Println("收到 GetModel 请求")
	// 实际场景可从插件配置加载支持的模型
	return &plugin.GetModelResponse{
		Model:           "00",           // 默认模型
		SupportedModels: []string{"00"}, // 支持的所有模型
	}, nil
}

// BuildRequest 构建协议请求数据（核心业务逻辑，根据协议自定义）
func (s *Server) BuildRequest(ctx context.Context, req *plugin.BuildRequestRequest) (*plugin.BuildRequestResponse, error) {
	s.cfg.Log.Printf("收到 BuildRequest 请求，命令: %s，参数: %v", req.Command, req.Params)

	// 1. 校验请求
	if req.Command == "" {
		errMsg := "命令不能为空"
		s.cfg.Log.Printf("BuildRequest 失败: %s", errMsg)
		return &plugin.BuildRequestResponse{
			Success: false,
			Error:   errMsg,
		}, nil
	}
	var request []byte
	var err error
	//命令分别为 开机，关机，雨量采集，温湿度采集，风量采集，风速采集
	switch req.Command {
	case "开机":
		request, err = s.plugins["继电器"].BuildRequest(5, 6, 0, 1)
	case "关机":
		request, err = s.plugins["继电器"].BuildRequest(5, 6, 0, 0)
	case "雨量":
		request, err = s.plugins["雨量"].BuildRequest(1, 3, 0, 1)
	case "百叶窗":
		request, err = s.plugins["百叶窗"].BuildRequest(2, 3, 500, 8)
	case "风速":
		request, err = s.plugins["风速"].BuildRequest(4, 3, 0, 1)
	case "风向":
		request, err = s.plugins["风向"].BuildRequest(3, 3, 0, 2)
	case "土壤":
		request, err = s.plugins["土壤"].BuildRequest(6, 3, 0, 4)
	default:
		errMsg := fmt.Sprintf("不支持的命令: %s", req.Command)
		s.cfg.Log.Printf("BuildRequest 失败: %s", errMsg)
		return &plugin.BuildRequestResponse{
			Success: false,
			Error:   errMsg,
		}, nil
	}
	if err != nil {
		errMsg := fmt.Sprintf("BuildRequest 失败: %s", err.Error())
		s.cfg.Log.Printf("BuildRequest 失败: %s", errMsg)
		return &plugin.BuildRequestResponse{
			Success: false,
			Error:   errMsg,
		}, nil
	}
	return &plugin.BuildRequestResponse{
		Success: true,
		Data:    request,
	}, nil
}

// ParseResponse 解析协议响应数据（核心业务逻辑，根据协议自定义）
func (s *Server) ParseResponse(ctx context.Context, req *plugin.ParseResponseRequest) (*plugin.ParseResponseResponse, error) {
	var sensorData *model.SensorData
	var err error
	startTime := time.Now()
	s.cfg.Log.Printf("收到 ParseResponse 请求，命令: %s，待解析数据: %x", req.Command, req.Data)

	// 1. 校验请求
	if len(req.Data) == 0 {
		errMsg := "待解析数据不能为空"
		s.cfg.Log.Printf("ParseResponse 失败: %s", errMsg)
		return &plugin.ParseResponseResponse{
			Success: false,
			Error:   errMsg,
		}, nil
	}
	if !s.isModbusData(req.Data) {
		errMsg := "数据不是modbus协议数据"
		s.cfg.Log.Printf("ParseResponse 失败: %s", errMsg)
		return &plugin.ParseResponseResponse{
			Success: false,
			Error:   errMsg,
		}, nil
	}
	switch req.Data[0] {
	case 0x01:
		sensorData, err = s.plugins["雨量"].ParseResponse(req.Data)
	case 0x02:
		sensorData, err = s.plugins["百叶窗"].ParseResponse(req.Data)
	case 0x04:
		sensorData, err = s.plugins["风速"].ParseResponse(req.Data)
	case 0x03:
		sensorData, err = s.plugins["风向"].ParseResponse(req.Data)
	case 0x05:
		sensorData, err = s.plugins["继电器"].ParseResponse(req.Data)
	case 0x06:
		sensorData, err = s.plugins["土壤"].ParseResponse(req.Data)
	default:
		errMsg := fmt.Sprintf("不支持的功能码: 0x%02X", req.Data[0])
		s.cfg.Log.Printf("ParseResponse 失败: %s", errMsg)
		return &plugin.ParseResponseResponse{
			Success: false,
			Error:   errMsg,
		}, nil
	}
	if err != nil {
		errMsg := fmt.Sprintf("ParseResponse 失败: %s", err.Error())
		s.cfg.Log.Printf("ParseResponse 失败: %s", errMsg)
		return &plugin.ParseResponseResponse{
			Success: false,
			Error:   errMsg,
		}, nil
	}
	return &plugin.ParseResponseResponse{
		Success: true,
		Data: &plugin.SensorData{
			Protocol:  sensorData.Protocol,
			Type:      sensorData.Type,
			Model:     sensorData.Model,
			Values:    sensorData.Values,
			Timestamp: sensorData.Timestamp,
			IsValid:   true,
		},
		ParseTime: time.Since(startTime).Microseconds(),
	}, nil
}

// isModbusData 判断数据是否为modbus协议数据 并且返回解析后的数据
func (s *Server) isModbusData(data []byte) bool {
	// Modbus RTU最小帧长度为3字节（地址+功能码+CRC低字节）
	if len(data) < 3 {
		return false
	}

	// 从站地址范围：1-247（0x01-0xF7），0为广播地址
	address := data[0]
	if address < 0x00 || address > 0xF7 {
		return false
	}

	// 功能码范围：1-255（0x01-0xFF），其中128-255为异常响应
	functionCode := data[1]
	if functionCode < 0x01 || functionCode > 0xFF {
		return false
	}

	// 对于正常功能码（1-127），最小数据长度应为3字节（含CRC）
	if functionCode >= 0x01 && functionCode <= 0x7F && len(data) < 3 {
		return false
	}

	// 对于异常功能码（128-255），最小数据长度应为3字节
	if functionCode >= 0x80 && functionCode <= 0xFF && len(data) < 3 {
		return false
	}
	return true
}

// --------------- 服务生命周期管理 ---------------

// Start 启动 gRPC 服务
func (s *Server) Start() error {
	// 1. 创建网络监听器
	listener, err := net.Listen("tcp", s.cfg.ListenAddr)
	if err != nil {
		return fmt.Errorf("监听地址 %s 失败: %w", s.cfg.ListenAddr, err)
	}
	s.listener = listener
	s.cfg.Log.Printf("gRPC 服务已监听: %s（TLS: %v）", s.cfg.ListenAddr, s.cfg.TLSEnabled)

	// 2. 创建 gRPC 服务实例
	s.grpcServer = grpc.NewServer(s.cfg.GetGRPCServerOpts()...)

	// 3. 注册插件服务
	plugin.RegisterPluginServiceServer(s.grpcServer, s)
	s.cfg.Log.Println("PluginService 服务已注册")

	// 4. 启动服务（非阻塞，通过 goroutine 运行）
	go func() {
		if err := s.grpcServer.Serve(s.listener); err != nil && !errors.Is(err, grpc.ErrServerStopped) {
			s.cfg.Log.Fatalf("gRPC 服务异常退出: %v", err)
		}
	}()

	// 5. 监听关闭信号（阻塞，直到收到信号）
	s.waitForShutdown()
	return nil
}

// waitForShutdown 等待关闭信号并执行优雅关闭
func (s *Server) waitForShutdown() {
	// 阻塞直到收到 SIGINT/SIGTERM 信号
	<-s.shutdownChan
	s.cfg.Log.Println("收到关闭信号，开始优雅关闭 gRPC 服务")

	// 1. 创建关闭上下文（带超时）
	shutdownCtx, cancel := context.WithTimeout(context.Background(), s.cfg.ShutdownTimeout)
	defer cancel()

	// 2. 优雅关闭 gRPC 服务
	done := make(chan struct{})
	go func() {
		s.grpcServer.GracefulStop() // 停止接收新请求，等待现有请求处理完成
		close(done)
	}()

	// 3. 等待关闭完成或超时
	select {
	case <-done:
		s.cfg.Log.Println("gRPC 服务已优雅关闭")
	case <-shutdownCtx.Done():
		s.cfg.Log.Println("gRPC 服务关闭超时，强制退出")
		s.grpcServer.Stop() // 强制关闭
	}

	// 4. 关闭监听器
	if err := s.listener.Close(); err != nil {
		s.cfg.Log.Printf("关闭监听器失败: %v", err)
	} else {
		s.cfg.Log.Println("监听器已关闭")
	}
}

// --------------- 工具函数 ---------------

// loadTLSCreds 加载 TLS 凭证（生产环境必备）
func loadTLSCreds(certPath, keyPath string) (credentials.TransportCredentials, error) {
	// 加载服务端证书和私钥
	cert, err := tls.LoadX509KeyPair(certPath, keyPath)
	if err != nil {
		return nil, fmt.Errorf("加载证书/私钥失败: %w", err)
	}

	// 配置 TLS 服务端选项
	tlsConfig := &tls.Config{
		Certificates: []tls.Certificate{cert},
		ClientAuth:   tls.NoClientCert, // 无需客户端证书（根据需求调整为 RequestClientCert/RequireAndVerifyClientCert）
	}

	return credentials.NewTLS(tlsConfig), nil
}
